﻿using PLCS.Domain.PLCConfigs;
using PLCS.EntityFrameworkCore.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
using System.Threading;

namespace PLCS.EntityFrameworkCore.PlcReadDatas;

public class PLCReadDataRepository : EfCoreRepository<PLCSDbContext, PLCReadData, Guid>, IPLCReadDataRepository
{
    public PLCReadDataRepository(IDbContextProvider<PLCSDbContext> dbContextProvider) : base(dbContextProvider)
    {
    }

    public async Task ChangeValueAsync(Guid Id, string value)
    {
        var readData = await GetAsync(Id);
        readData.ChangeValue(value);
        await UpdateAsync(readData);
    }

    public async Task DeleteAllAsync()
    {
        var dbContext = await GetDbContextAsync();
        await dbContext.Database.ExecuteSqlRawAsync(
            $"DELETE FROM T_PLCReadDatas"
        );
    }

    public async Task<PLCReadData?> FindPLCReadDataByNoAsync(string no)
    {
        var queryable = await GetQueryableAsync();
        queryable = queryable.Include(x => x.PLCConfig).Where(x => x.PLCReadDataNo == no);
        return await AsyncExecuter.FirstOrDefaultAsync(queryable);
    }

    public async Task<IEnumerable<PLCReadData>> GetPLCReadDatasListAsync()
    {
        var queryable = await GetQueryableAsync();
        queryable = queryable.Include(x => x.PLCConfig)
            .OrderBy(x => x.PLCConfigId).ThenBy(x => x.StartBit)
            .AsNoTracking();
        return await AsyncExecuter.ToListAsync(queryable);
    }

    public async Task UpdateManyOnlyCurrentValueAsync(IEnumerable<PLCReadData> pLCReadDatas, bool autoSave = false, CancellationToken cancellationToken = default)
    {
        cancellationToken = GetCancellationToken(cancellationToken);
        var dbContext = await GetDbContextAsync();

        foreach (var item in pLCReadDatas)
        {
            dbContext.Set<PLCReadData>().Attach(item);

            var entry = dbContext.Entry(item);
            entry.Property(x => x.CurrentValue).IsModified = true;
            entry.Property(x => x.HistoricalValue).IsModified = true;
            entry.Property(x => x.LastModificationTime).IsModified = true;
        }

        if (autoSave)
        {
            await dbContext.SaveChangesAsync(cancellationToken);
        }
    }
}